package com.generate.util;

import com.generate.util.dict.NumberDict;
import lombok.extern.slf4j.Slf4j;

import java.io.*;

/**
 * 文件工具类
 * <p>
 * User: by 蒋文哲 Date: 2017/3/30 Version: 1.0
 * </p>
 */
@Slf4j
public class FileUtil {

    /**
     * 创建文件
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean createFile(String filePath) {
        File file = new File(filePath);
        log.info("创建目标目录开始...");
        if (file.exists()) {
            log.info("文件已存在!");
            return false;
        }
        if (file.isDirectory()) {
            log.info("文件不能是目录!");
            return false;
        }
        if (!file.getParentFile().exists()) {
            log.info("目标所在文件目录不存在，准备创建...");
            if (!file.getParentFile().mkdirs()) {
                log.info("目标所在文件目录创建失败!");
                return false;
            }
        }
        log.info("创建目标文件...");
        try {
            if (!file.createNewFile()) {
                log.info("创建目标文件失败!");
                return false;
            }
        } catch (IOException e) {
            log.error("目标文件创建异常!", e);
            return false;
        }
        log.info("创建目标文件成功!");
        return true;
    }

    /**
     * 创建目录
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean createDirectory(String filePath) {
        File file = new File(filePath);
        log.info("创建目标目录开始...");
        if (file.exists()) {
            log.info("目录已存在!");
            return false;
        }
        if (file.isFile()) {
            log.info("目录不能是文件!");
            return false;
        }
        return file.mkdirs();
    }

    /**
     * 删除文件
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean deleteFile(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            log.info("目标文件不存在!");
            return false;
        }
        if (file.isFile()) {
            boolean flag = file.delete();
            log.info("目标文件删除：{}", flag);
            return flag;
        }
        log.info("目标文件非文件，无法删除!");
        return false;
    }

    public static void recurDelete(File f) {
        try {
            for (File fi : f.listFiles()) {
                if (fi.isDirectory()) {
                    recurDelete(fi);
                } else {
                    fi.delete();
                }
            }
            f.delete();
        } catch (NullPointerException n) {
            log.error("目标为空不能删除");
        }
    }

    /**
     * 文件重命名
     *
     * @param filePath    文件路径
     * @param oldFileName 旧文件名
     * @param newFileName 新文件名
     * @return boolean
     */
    public static boolean renameFile(String filePath, String oldFileName, String newFileName) {
        File directory = new File(filePath);
        if (directory.isDirectory()) {
            if (!oldFileName.equals(newFileName)) {
                File oldFile = new File(filePath.concat(File.separator).concat(oldFileName));
                File newFile = new File(filePath.concat(File.separator).concat(newFileName));
                if (!oldFile.exists()) {
                    log.info("旧文件不存在，无法重命名!");
                    return false;
                }
                if (newFile.exists()) {
                    log.info("新文件已存在，无法重命名!");
                } else {
                    boolean flag = oldFile.renameTo(newFile);
                    log.info("目标文件重命名：{}", flag);
                    return flag;
                }
            } else {
                log.info("文件名相同无法重命名!");
            }
        } else {
            log.info("文件路径必须是目录!");
        }
        return false;
    }

    /**
     * 复制文件
     *
     * @param srcFileName    String
     * @param targetFileName String
     * @param overlay        boolean
     * @return boolean
     */
    public static boolean copyFile(String srcFileName, String targetFileName, boolean overlay) {
        File srcFile = new File(srcFileName);
        log.info("判断源文件是否存在");
        if (!srcFile.exists()) {
            log.info("源文件{}不存在!", srcFileName);
            return false;
        } else if (!srcFile.isFile()) {
            log.info("复制文件失败，源文件{}不是一个文件!", srcFileName);
            return false;
        }
        log.info("判断目标文件是否存在");
        File targetFile = new File(targetFileName);
        if (targetFile.exists()) {
            if (!overlay) {
                log.info("不允许覆盖,文件已经存在，无法复制!overlay:{}", overlay);
                return false;
            }
        } else {
            log.info("判断目标文件是否存在");
            if (!targetFile.getParentFile().exists()) {
                log.info("目标文件所在目录不存在!");
                if (!targetFile.getParentFile().mkdirs()) {
                    log.info("复制文件失败：创建目标文件所在目录失败!");
                    return false;
                }
            }
        }
        log.info("复制文件开始!");
        int byteRead;
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(targetFile);
            byte[] buffer = new byte[NumberDict.BYTE_NUM * NumberDict.FOUR];

            while ((byteRead = in.read(buffer)) != NumberDict.MINUS_ONE) {
                out.write(buffer, NumberDict.ZERO, byteRead);
            }
            log.info("复制文件结束!");
            return true;
        } catch (FileNotFoundException e) {
            log.info("文件复制异常:", e);
            return false;
        } catch (IOException e) {
            log.info("文件复制异常:", e);
            return false;
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                log.info("关闭IO流异常:", e);
            }
        }
    }

    /**
     * 判断是否为可执行文件
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean canExecute(String filePath) {
        return new File(filePath).canExecute();
    }

    /**
     * 判断是否为可读文件
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean canRead(String filePath) {
        return new File(filePath).canRead();
    }

    /**
     * 判断是否为可写文件
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean canWrite(String filePath) {
        return new File(filePath).canWrite();
    }

    /**
     * 判断是否存在路径
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean isExists(String filePath) {
        return new File(filePath).exists();
    }

    /**
     * 判断是否为目录
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean isDirectory(String filePath) {
        return new File(filePath).isDirectory();
    }

    /**
     * 判断是否为文件
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean isFile(String filePath) {
        return new File(filePath).isFile();
    }

    /**
     * 判断是否为隐藏文件
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean isHidden(String filePath) {
        return new File(filePath).isHidden();
    }

    /**
     * 判断是否为绝对路径
     *
     * @param filePath 文件路径
     * @return boolean
     */
    public static boolean isAbsolute(String filePath) {
        return new File(filePath).isAbsolute();
    }

    /**
     * 移动文件
     *
     * @param sourceFilePath String
     * @param targetFilePath String
     * @param flag           boolean
     */
    public void moveFile(String sourceFilePath, String targetFilePath, boolean flag) {

    }

    /**
     * 获取文件count
     *
     * @param filePath String
     */
    public void getFileCount(String filePath) {

    }

    /**
     * 获取文件size
     *
     * @param filePath String
     */
    public void getFileSize(String filePath) {

    }

    /**
     * 查找文件
     *
     * @param filePath String
     * @param target   String
     */
    public void searchFile(String filePath, String target) {

    }

    /**
     * 获取文件绝对路径
     *
     * @param filePath String
     */
    public void getFileAttribute(String filePath) {

    }

    /**
     * 获取文件后缀
     *
     * @param filePath String
     * @param suffix   String
     */
    public void getFileBySuffix(String filePath, String suffix) {

    }
}
